// Modelo Sistemas de recoleccion de piezas!!!
#include "simlib.c"

//Definicion de tipos de eventos
#define llegada		        1
#define arribo        	    2
#define partida		        3
//Definimos tipo de transfer para hacerlos mas claros
#define tiemposim           1
#define tevento             2
#define tpartida            3
//Definimos los tipos de cola
#define colarapida          0
#define colalenta           1
//Definicion de constantes
#define semilla             7
#define maxsimulacion       10080  //Tiempo maximo de simulacion (1 semana en minutos)
#define interavion          180 // 3 horas en minutos por cada llegada de avion
#define mincarga            240 //minima cantidad de pasajeros en un avion
#define maxcarga            350 //maxima cantidad de pasajeros en un avion
#define interpeaton         0.2 //0.2 minutos es el tiempo de llegada de un peaton a la aduana
#define revisacionrapida    0.55 //0.55 minutos tarda en revisar uno en la cola rapida
#define agentescolarapida   2   //cantidad de agentes en cola rapida
#define revisacionlentamin  3   //3 minutos es el minimo de una revisacion completa
#define revisacionlentamax  6   //6 minutos es el maximo de una revisacion completa
#define agentescolalenta    1   //cantidad de agentes en cola lenta
//Colas utilizadas para calcular los estadisticos
#define servidorlento       1
#define servidorrapido1     2
#define servidorrapido2     3
// Sampst
#define demora_colarapida   1
#define demora_colalenta    2

//Declaracion de variables
int cpeatones, randomtest;  //variables que iremos usando
int cola[2];                //defimos las variables que llevaran cuanta gente hay esperando en cada cola
bool agenteslibres[3]= {true,true,true}; //agente cola lenta, agente cola rapida A, agente cola rapida B
float porcentaje;
int revisados, totales, sr;

// Declaracion de nuestras funciones
void inicializa(void);
void rllegada(void);
void rarribo(void);
void rpartida(void);
void reporte(void);

//Inicio de simulacion
main()
{
	init_simlib();                      // Initializar Simlib
	maxatr = 3;                         // Establecer maxatr = M ximo n£mero de Atributos utilizados
	inicializa();                       // Initializa los parametros de la simulacion

	while (sim_time < maxsimulacion) //Mientras el tiempo actual no complete lo que se desea simular
	{
		//if (sim_time > 35,2) 
		//		   system("pause");
        timing(); //Buscar proximo evento
		switch( next_event_type ) //Determinamos que tipo de evento sera!
        {
		    case llegada: rllegada(); break;    //Si el evento es una llegada de avion
			case arribo: rarribo(); break;      //Si el evento es un arribo de peaton a aduana
			case partida:rpartida(); break;     //Si el evento es una partida de peaton
        }
	}
    reporte();
}

void inicializa(void)// Initializamos los parametros de la simulacion
{
     printf( "Inicializacion de la simulacion... \n");
     printf( "___________________________________ \n");
     cpeatones = 0;
     revisados = 0;
     totales = 0;
	randomtest= uniform(1,10,semilla);
	transfer[tiemposim] = sim_time + expon(interavion,semilla);
	transfer[tevento] = llegada;
	list_file(INCREASING,LIST_EVENT);
}

void rllegada(void)  // Evento de llegada de avion
{
    if (cpeatones == 0) //si la cantidad de pasajeros es nula, mandamos uno de los nuevos a ser atendido
    {
        transfer[tiemposim]= sim_time + expon(interpeaton, semilla);
        transfer[tevento]= arribo;
        list_file(INCREASING,LIST_EVENT);
    }
    cpeatones+= uniform(mincarga,maxcarga,semilla);
    //llegada del proximo avion
    transfer[tiemposim] = sim_time + expon(interavion,semilla);
	transfer[tevento] = llegada;
	list_file(INCREASING,LIST_EVENT);
}

void rarribo(void)  //Evento de llegada de pasajero
{
    if (cpeatones > 0) //si todavia hay peatones esperando en la lista
    {
        cpeatones--; //reduciomos la cantidad de peatones y generamos proximo arribo a aduana
        transfer[tiemposim]= sim_time + expon(interpeaton, semilla);
        transfer[tevento]= arribo;
        list_file(INCREASING,LIST_EVENT);
    }
    totales++; //cantidad de pasajeros que van llegando
    if (randomtest == 0) //si te toca revision lenta...
    {
        revisados++; //cantidad de pasajeros que le toca la revisacion
        randomtest= uniform(1,10,semilla); //generamos el proximo sorteo de revision
        if (list_size[servidorlento] == 0) //Si el agente esta libre a pesar de no haber cola
        {
    	   list_file(FIRST, servidorlento);
           sampst(0.0, demora_colalenta);                
            
           transfer[tiemposim]= sim_time + uniform(revisacionlentamin,revisacionlentamax,semilla);
           transfer[tevento]= partida;
           transfer[tpartida]= servidorlento;
           list_file(INCREASING,LIST_EVENT);
        }
        else 
        {
             transfer[1] = sim_time;
             list_file(LAST, colalenta);//si el agente esta ocupado va a la cola...
        }
    }
    else
    {
        randomtest--;
        if ((list_size[servidorrapido1] == 0) or (list_size[servidorrapido2]==0)) //Si alguno de los dos agentes rapidos esta libre
        {
            if (list_size[servidorrapido1] == 0)
            {
    	       list_file(FIRST, servidorrapido1);
    	       transfer[tpartida]= servidorrapido1;
            }
            else
            {    
                list_file(FIRST, servidorrapido2);
                transfer[tpartida]= servidorrapido2;
            }
            transfer[tiemposim]= sim_time + expon(revisacionrapida,semilla);
            transfer[tevento]= partida;
            list_file(INCREASING,LIST_EVENT);
            sampst(0.0, demora_colarapida);
        }
        else 
        {
             transfer[1] = sim_time;
             list_file(LAST, colarapida);//si el agente esta ocupado va a la cola...
        }
    }
}

void rpartida(void) //partida de fin de revisacion para un peaton
{
    sr = (int)transfer[3]; //variable para que no se pierda el transfer 3 desp de hacer el list_file
    list_remove(FIRST, sr);//disminuimos la cola del servidor    
    
    if (transfer[tpartida] == servidorlento)
    {
       if (list_size[colalenta] > 0)
	   {
          list_remove(FIRST, colalenta); //sacamos uno de la cola lenta
          sampst(sim_time - transfer[1], demora_colalenta); //estadisticos
          list_file(FIRST, servidorlento); //el que sacamos de la cola lo ponemos en el servidor
          //generamos nueva partida
          transfer[tiemposim]= sim_time + uniform(revisacionlentamin,revisacionlentamax,semilla);
          transfer[tevento]= partida;
          transfer[tpartida]= colalenta;
          list_file(INCREASING,LIST_EVENT);
        }
    }
    else
    {
       if (list_size[colarapida] > 0)
	   {
          list_remove(FIRST, colarapida); //sacamos uno de la cola lenta
          sampst(sim_time - transfer[1], demora_colarapida); //estadisticos
          list_file(FIRST, sr); //el que sacamos de la cola lo ponemos en el servidor
          //generamos nueva partida
          transfer[tiemposim]= sim_time + expon(revisacionrapida,semilla);
          transfer[tevento]= partida;
          transfer[tpartida]= sr;
          list_file(INCREASING,LIST_EVENT);
        }
    }
}

void reporte( void )  /* Generar Reporte de la Simulaci¢n */
{
	/* -------- Por pantalla -------- */
	printf( "Resultados de la simulacion del sistema aduanero \n");
	printf( "___________________________________ \n");
	filest(servidorrapido1);
	printf("Utilizacion del agente que no revisa 1: %f \n", transfer[1]);
	filest(servidorrapido2);
	printf("Utilizacion del agente que no revisa 2: %f \n", transfer[1]);
	filest(servidorlento);
	printf("Utilizacion del agente de revision lento: %f \n", transfer[1]);
	
    sampst(0.0,-colarapida);
	printf("Demora media en el servidor que no revisa: %f \n", transfer[1]);
	sampst(0.0,-colalenta);
	printf("Demora media en el servidor de revision lento: %f \n", transfer[1]);
	
    filest(colarapida);
	printf("Numero medio en servidor que no revisa: %f \n", transfer[1]);
	filest(colalenta);
	printf("Numero medio en servidor de revision lento: %f \n", transfer[1]);
	
    porcentaje = ((float)revisados/(float)totales)*100;
    printf("Porcentaje de pasajeros revisados: %10.3f \n", porcentaje);
    printf( "___________________________________ \n");
    system("pause");
}
